package com.xiaowanzi.transporter.handler;

import com.xiaowanzi.transporter.constants.MessageTypeEnum;
import com.xiaowanzi.transporter.model.Message;
import com.xiaowanzi.transporter.model.TimeMetadata;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

@Sharable
public class HeartbeatHandler extends SimpleChannelInboundHandler<Message> {

  private volatile TimeMetadata metadata = new TimeMetadata(System.currentTimeMillis());

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
//    ctx.executor().scheduleAtFixedRate(new PingTask(ctx.channel()), 1, 2, TimeUnit.SECONDS);
//    ctx.executor().scheduleAtFixedRate(new HeartbeatTask(ctx.channel()), 1, 1, TimeUnit.SECONDS);
    new PingTask(ctx.channel()).run();
    super.channelRegistered(ctx);
  }

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, Message message) throws Exception {

  }

  private static final class PingTask implements Runnable {

    private Channel channel;

    public PingTask(Channel channel) {
      this.channel = channel;
    }

    @Override
    public void run() {
      if (!channel.isActive()) {
        channel.close();
        return;
      }

      System.out.println("send ping message " + System.currentTimeMillis());
      Message ping = new Message();
      ping.setMessageType(MessageTypeEnum.PING);
      channel.writeAndFlush(ping);
    }
  }

  private final class HeartbeatTask implements Runnable {

    private Channel channel;

    public HeartbeatTask(Channel channel) {
      this.channel = channel;
    }

    @Override
    public void run() {
      if (!channel.isActive()) {
        channel.close();
        return;
      }

      long lastTouchTime = metadata.getLastTouchTime();
      long currentTime = System.currentTimeMillis();
      System.out.println("check touch time, lastTouchTime: "
          + lastTouchTime + ", currentTime: " + currentTime);
      if (currentTime - lastTouchTime > 2000) {
        channel.close();
      }
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    cause.printStackTrace();
  }
}
